#include "smart-device-protocol.h"

SmartDeviceProtocol::SmartDeviceProtocol()
{
}

SmartDeviceProtocol::SmartDeviceProtocol(const vector<uint8_t> &packet)
    : packet(packet)
{
}

/**
 * 添加包头
*/
void SmartDeviceProtocol::addPakcetHead(uint16_t head)
{
	packet.push_back(head >> 8);
	packet.push_back(head & 0xff);
}

/**
 * 添加地址 4个字节 32位 高字节在前
*/
void SmartDeviceProtocol::addDeviceAddress(uint32_t addr)
{
	for(int i = 0; i < 4; i++)
	{
		packet.push_back(addr >> 24);
		addr = addr << 8;
	}
}

/**
 * 添加ID
*/
void SmartDeviceProtocol::addPacketID(uint8_t id)
{
	packet.push_back(id);
}

/**
 * 添加内容
*/
void SmartDeviceProtocol::addPacketData(uint8_t *data, uint16_t size)
{
	//添加长度
	packet.push_back(size >> 8);
	packet.push_back(size & 0xff);

	//添加数据
	for(int i = 0; i < size; i++)
	{
		packet.push_back(data[i]);
	}
}

/**
 * 添加校验位
*/
void SmartDeviceProtocol::addCRC16(void)
{
	uint16_t crc16Value = calc_crc16(packet.data(), packet.size());
	packet.push_back(crc16Value >> 8);
	packet.push_back(crc16Value & 0xff);
}

uint8_t *SmartDeviceProtocol::packetData(void)
{
	return packet.data();
}

uint16_t SmartDeviceProtocol::packetLenth(void)
{
	return packet.size();
}

SmartDeviceProtocol SmartDeviceProtocol::makeDoorLockProtocol(uint8_t deviceType,
                                                              uint8_t opCode,
                                                              uint8_t deviceNumber)
{
	SmartDeviceProtocol protocol;

	protocol.addPakcetHead();
	protocol.addDeviceAddress(DOOR_LOCK_DEVICE_ADDR);
	protocol.addPacketID(REQ_PACKET);
	uint8_t data[] = {deviceType, opCode, deviceNumber};
	protocol.addPacketData(data, sizeof(data));
	protocol.addCRC16();

	return protocol;
}

SmartDeviceProtocol SmartDeviceProtocol::makeElectricalProtocol(uint8_t deviceType, uint8_t opCode, uint8_t deviceNumber)
{
	SmartDeviceProtocol protocol;

	protocol.addPakcetHead();
	protocol.addDeviceAddress(ELECTRICAL_DEVICE_ADDR);
	protocol.addPacketID(REQ_PACKET);
	uint8_t data[] = {deviceType, opCode, deviceNumber};
	protocol.addPacketData(data, sizeof(data));
	protocol.addCRC16();

	return protocol;
}

SmartDeviceProtocol SmartDeviceProtocol::makeSensorcalProtocol(uint8_t deviceType, uint8_t opCode, uint8_t deviceNumber)
{
	SmartDeviceProtocol protocol;

	protocol.addPakcetHead();
	protocol.addDeviceAddress(SENSOR_DEVICE_ADDR);
	protocol.addPacketID(REQ_PACKET);
	uint8_t data[] = {deviceType, opCode, deviceNumber};
	protocol.addPacketData(data, sizeof(data));
	protocol.addCRC16();

	return protocol;
}

SmartDeviceProtocol SmartDeviceProtocol::makeSniffingProtocol(uint8_t deviceType, uint8_t opCode, uint8_t deviceNumber)
{
	SmartDeviceProtocol protocol;

	protocol.addPakcetHead();
	protocol.addDeviceAddress(SNIFFING_DEVICE_ADDR);
	protocol.addPacketID(REQ_PACKET);
	uint8_t data[] = {deviceType, opCode, deviceNumber};
	protocol.addPacketData(data, sizeof(data));
	protocol.addCRC16();

	return protocol;
}

SmartDeviceProtocol SmartDeviceProtocol::makeProtocolFromPacket(const vector<uint8_t> &packet)
{
	return SmartDeviceProtocol(packet);
}

//================解析应答包的地方================
uint16_t SmartDeviceProtocol::getPacketHead(void) const
{
	packet_t *pkt = (packet_t *)packet.data();
	return (pkt->head[0] << 8 | pkt->head[1]);
}

// 获取地址
uint32_t SmartDeviceProtocol::getPacketAddr(void) const
{
	packet_t *pkt = (packet_t *)packet.data();
	uint32_t  packetAddr =
	    (pkt->addr[0] << 24) | (pkt->addr[1] << 16) | (pkt->addr[2] << 8) | (pkt->addr[3] << 0);
	return packetAddr;
}

uint8_t SmartDeviceProtocol::getPacketID(void) const
{
	packet_t *pkt = (packet_t *)packet.data();
	return pkt->pid;
}

uint16_t SmartDeviceProtocol::getPacketDataLen(void) const
{
	packet_t *pkt = (packet_t *)packet.data();
	return (pkt->len[0] << 8 | pkt->len[1]);
}

uint8_t *SmartDeviceProtocol::getPacketData(void) const
{
	packet_t *pkt = (packet_t *)packet.data();
	return getPacketDataLen() ? &pkt->data[0] : nullptr;
}

uint16_t SmartDeviceProtocol::getPacketCRC16(void) const
{
	int packetSize = packet.size();
	return (packet[packetSize - 2] << 8 | packet[packetSize - 1]);
}

uint8_t SmartDeviceProtocol::getPakcetErrorCode(void) const
{
	packet_t *pkt = (packet_t *)packet.data();
	return pkt->data[0];
}

void SmartDeviceProtocol::showPacket(void) const
{
	packet_t *pkt = (packet_t *)packet.data();
	// 4个16进制显示 [0] 成员高字节 [1] 低字节
	printf("packet head : %04x\n", getPacketHead());
	printf("packet addr : %08x\n", getPacketAddr());
	printf("packet id   : %02x\n", getPacketID());
	printf("packet len  : %04x\n", getPacketDataLen());
	printf("packet data : ");
	uint16_t datalen = getPacketDataLen();
	uint8_t *data    = getPacketData();
	for(int i = 0; i < datalen; i++)
	{
		printf("%02x ", data[i]);
	}
	printf("\n");
	printf("packet sum: %04x\n", getPacketCRC16());
}

bool SmartDeviceProtocol::isErrorPacket(void)
{
	uint16_t crc16Value = calc_crc16(packet.data(), packet.size() - 2);

	return getPacketCRC16() != crc16Value;
}
